package com.hp.bon.sgw.wh.channel;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.simpleframework.http.Request;
import org.simpleframework.http.Response;
import org.simpleframework.http.core.Container;
import org.simpleframework.http.core.ContainerProcessor;
import org.simpleframework.http.core.ContainerSelector;
import org.simpleframework.http.core.ContainerServer;
import org.simpleframework.transport.connect.Connection;
import org.simpleframework.transport.connect.SocketConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayMobilePublicMessageMatcherSendRequest;
import com.alipay.api.response.AlipayMobilePublicMessageMatcherSendResponse;
import com.google.gson.Gson;
import com.hp.bon.sgw.Constants;
import com.hp.bon.sgw.Constants.NodeStatus;
import com.hp.bon.sgw.Constants.ResultCode;
import com.hp.bon.sgw.bean.XmlMessage;
import com.hp.bon.sgw.core.BuzProcessorManager;
import com.hp.bon.sgw.core.CallParam;
import com.hp.bon.sgw.core.InprogressMessageQueue;
import com.hp.bon.sgw.core.channel.IChannel;
import com.hp.bon.sgw.domain.Node;
import com.hp.bon.sgw.domain.SGWChannel;
import com.hp.bon.sgw.service.ConfigListener;
import com.hp.bon.sgw.service.ConfigService;
import com.hp.bon.sgw.start.SpringContext;
import com.hp.bon.sgw.util.RSAUtil;
import com.hp.bon.sgw.wh.Constants.AliParam;
import com.hp.bon.sgw.wh.bean.MessageRemaind;
import com.hp.bon.sgw.wh.bean.SetChargeTaobao;
import com.hp.bon.sgw.wh.channel.handler.BalanceTaobaoHandler;
import com.hp.bon.sgw.wh.channel.handler.SignTaobaoHandler;
import com.hp.bon.sgw.wh.channel.handler.TaobaoHandler;
import com.hp.bon.sgw.wh.service.WHConfigService;
import com.hp.bon.sgw.wh.utils.DESCryptoUtil;
import com.hp.bon.sgw.wh.utils.SignUtilsImpl;
import com.hp.ocs.diameter.DiameterUtils;
import com.hp.ocs.diameter.message.AVP;
import com.hp.ocs.diameter.message.AVP_Grouped;
import com.hp.ocs.diameter.message.AVP_UTF8String;
import com.hp.ocs.diameter.message.AVP_Unsigned64;
import com.hp.ocs.diameter.message.InvalidAVPLengthException;
import com.hp.ocs.diameter.message.Message;

/**
 * 
 * @ClassName: TaobaoChannel   
 * @Description: 淘宝接口  
 * @author: Sue  
 * @date:2014年11月20日 下午5:47:51
 */
public class TaobaoChannel implements Container, ConfigListener, IChannel {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = LoggerFactory.getLogger(TaobaoChannel.class);
	private ContainerServer server = null;
	private SGWChannel channel;
	protected ConfigService confSrv;
	private MultiThreadedHttpConnectionManager connectionManager;
	private HttpClient httpClient;
	
	private WHConfigService whConfigService;

	public TaobaoChannel(SGWChannel channel) {
		this.channel = channel;
		confSrv = SpringContext.getInstance().getConfigService();
		whConfigService = SpringContext.getApplicationContext().getBean(WHConfigService.class);
	}

	@Override
	public SGWChannel getSGWChannel() {
		return this.channel;
	}

	@Override
	public int getThreadPoolSize() {
		return executor.getPoolSize();
	}

	@Override
	public int getThreadPoolQueueSize() {
		return executor.getQueue().size();
	}

	@Override
	public int getThreadPoolActiveCount() {
		return executor.getActiveCount();
	}

	@Override
	public int getNodeSendQueueSize(String nodeHostId) {
		return 0;
	}

	ThreadPoolExecutor executor;
	ThreadPoolExecutor collector;

	private static String tbChargePath = "tbcharge";//充值接口
	private static String tbSignPath = "tbsign";//签约解约接口
	private static String tbMessageRemaind = "messageRemaind";//支付宝钱包接口
	private static String tbRemainQuery = "remainQuery";//支付宝即时充可用余额查询
	private Connection connection;

	@Override
	public void start() throws IOException {
		logger.info("start Taobao channel:" + channel.toString() + " ...");
		String key = "sgw.taobaochannel.thread.max";
		int maxThreads = confSrv.getIntValue(key, 20);
		logger.info(key + " :" + maxThreads);
		String endPoint = this.channel.getUri();
		if (endPoint == null) {
			logger.warn("channel dont't defined uri");
			return;
		}
		logger.info("start sgw TaobaoChannel server portal at " + endPoint);

		try {
			URL srvURL = new URL(endPoint);
			int port = srvURL.getPort();
			//找不到端口就启动失败
			if (port == -1) {
				logger.info("start taobaoWarringChannel error : port Not defined");
				return ;
			}
			String host = srvURL.getHost();
			if (host.equals("127.0.0.1") || host.equalsIgnoreCase("localhost")) {
				host = "0.0.0.0";
			}
			server = new ContainerServer(this, maxThreads);

			connection = new SocketConnection(server);
			SocketAddress address = new InetSocketAddress(host, port);
			connection.connect(address);
			collector = ((ContainerSelector) ((ContainerProcessor) server.getProcessor()).getSelector()).getCollect().getQueue();
			executor = ((ContainerSelector) ((ContainerProcessor) server.getProcessor()).getSelector()).getExecutor().getQueue();
			connectionManager = new MultiThreadedHttpConnectionManager();
			// ... configure connectionManager ...
			httpClient = new HttpClient(connectionManager);
			httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(10000);
			httpClient.getHttpConnectionManager().getParams().setSoTimeout(45000);

			this.channel.setStatus(NodeStatus.ON_LINE);
			confSrv.updateChannelStatus2DB(this.channel.getId(),NodeStatus.ON_LINE);
		} catch (IOException e) {
			logger.error("start Taobao channel " + this.channel.toString()+ " err " + e);
		}
	}

	@Override
	public void stop() {
		logger.info("stop Taobao channel");
		if (server != null) {
			try {
				server.stop();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if (connectionManager != null) {
			connectionManager.shutdown();
		}

		this.channel.setStatus(NodeStatus.OFF_LINE);
		confSrv.updateChannelStatus2DB(this.channel.getId(),NodeStatus.OFF_LINE);
		
		try {
			logger.info("wait 3s to exit...");
			Thread.sleep(3*1000);
		} catch (InterruptedException e) {
			logger.warn("Thread.sleep InterruptedException:",e);
		}
	}
	
	@Override
	public void handle(Request request, Response response) {
		
		logger.info("receive request from " + request.getClientAddress() + "; "	+ request.toString());
		
		String requestPath = request.getPath().getPath();
		if (requestPath.endsWith(tbChargePath)) {
			tbChargeHandle(request, response);
			return ;
		}else if(requestPath.endsWith(tbSignPath)){
			tbSignHandle(request,response);
			return ;
		}else if(requestPath.endsWith(tbMessageRemaind)){
			sendMessageRemaindRequest(request,response);
		}else if(requestPath.endsWith(tbRemainQuery)){
			sendRemainQueryRequest(request, response);
		}
		else{
			logger.debug("request path is invalid:"	+ request.getPath().getPath()+ " , ignore this request.");
		}
		
	}
	
	@Override
	public int sendRequest(CallParam callParam) {
		if (logger.isDebugEnabled()) {
			logger.debug(callParam.getSessionId()+ ", prepare forward request to TaoBao:"+ callParam.getToNode().getServerUrl());
		}
		
		if(callParam.getCapability().equals("QuestCharge.Taobao")){
			return sendTbChargeRequest(callParam);
		}else if(callParam.getCapability().equals("BalanceWarning.Taobao")){
			return sendTbWarringRequest(callParam);
		}
//		else if(callParam.getCapability().equals("MessageRemaind.Taobao")){
//			return sendMessageRemaindRequest(callParam);
//		}
		
		return -1 ;
	}

	@Override
	public void addPersist(Node node) {
	}

	@Override
	public void deletePersist(Node node) {
	}

	@Override
	public Set<String> monitorConfKeys() {
		return null;
	}

	@Override
	public void onConfigUpdated(String updatedKey) {
	}
	
	
	/**
	 * 
	 * @MethodName: tbChargeHandle   
	 * @Description: 实现代扣结果接收接口  
	 * @param @param request
	 * @param @param response  
	 * @return void  
	 * @throws
	 */
	public void tbChargeHandle(Request request, Response response) {
		// 实现代扣结果接收接口 (接收淘宝的HTTP请求)
		// http://host:port/resource?
		// sign=xx&sign_type=xx&alipay_order_id=xx&order_status=xx
		// &tb_order_id=xx&out_order_id=xx&seller_alipay_id=xx
		// &deduct_money=xx&order_pay_time=xx
		long receiveTime = System.currentTimeMillis();
		PrintStream body = null;
		try {
			body = response.getPrintStream();
			response.set("Content-Type", "text/xml;charset=GBK");
			response.set("Server", "HP Asyn Server )");
			response.setDate("Date", receiveTime);
			response.setDate("Last-Modified", receiveTime);

			//  增加IP校验
			String IP = request.getClientAddress().getAddress().getHostAddress();

			// 基本参数
			// String sign = request.getParameter("sign");
			// String sign_type = request.getParameter("sign_type");

			// 参数需要URLDecode

			// 淘宝订单数字ID
			String _tb_order_id = request.getParameter("tb_order_id");
			if (_tb_order_id == null) {
				errorAck(body, "tb_order_id is null");
				return;
			}
			String tb_order_id = URLDecoder.decode(_tb_order_id, "GBK");
			// 商户订单号
			String _out_order_id = request.getParameter("out_order_id");
			if (_out_order_id == null) {
				errorAck(body, "out_order_id is null");
				return;
			}
			String out_order_id = URLDecoder.decode(_out_order_id, "GBK");
			// 卖家支付宝账号
			String _seller_alipay_id = request.getParameter("seller_alipay_id");
			if (_seller_alipay_id == null) {
				errorAck(body, "seller_alipay_id is null");
				return;
			}
			String seller_alipay_id = URLDecoder.decode(_seller_alipay_id,"GBK");
			// 代扣金额
			String _deduct_money = request.getParameter("deduct_money");
			if (_deduct_money == null) {
				errorAck(body, "deduct_money is null");
				return;
			}
			String deduct_money = URLDecoder.decode(_deduct_money, "GBK");
			// 支付宝订单号
			String _alipay_order_id = request.getParameter("alipay_order_id");
			if (_alipay_order_id == null) {
				errorAck(body, "alipay_order_id is null");
				return;
			}
			String alipay_order_id = URLDecoder.decode(_alipay_order_id, "GBK");
			// 代扣状态
			String _order_status = request.getParameter("order_status");
			if (_order_status == null) {
				errorAck(body, "order_status is null");
				return;
			}
			String order_status = URLDecoder.decode(_order_status, "GBK");
			// 代扣付款时间
			String _order_pay_time = request.getParameter("order_pay_time");
			if (_order_pay_time == null) {
				errorAck(body, "order_pay_time is null");
				return;
			}
			String order_pay_time = URLDecoder.decode(_order_pay_time, "GBK");

			// 签名验证,验证通过，不通过

			// 验证通过后
			// 封装淘宝的request
			Element serviceInformation = DocumentHelper.createElement("Service_Information");
			Element element = null;
			if (tb_order_id != null) {
				element = serviceInformation.addElement("tb_order_id");
				element.setText(tb_order_id);
			}
			if (out_order_id != null) {
				element = serviceInformation.addElement("out_order_id");
				element.setText(out_order_id);
			}
			if (seller_alipay_id != null) {
				element = serviceInformation.addElement("seller_alipay_id");
				element.setText(seller_alipay_id);
			}
			if (deduct_money != null) {
				element = serviceInformation.addElement("deduct_money");
				element.setText(deduct_money);
			}
			if (alipay_order_id != null) {
				element = serviceInformation.addElement("alipay_order_id");
				element.setText(alipay_order_id);
			}
			if (order_status != null) {
				element = serviceInformation.addElement("order_status");
				element.setText(order_status);
			}
			if (order_pay_time != null) {
				element = serviceInformation.addElement("order_pay_time");
				element.setText(order_pay_time);
			}
			String ALI_HOST = whConfigService.getValue(AliParam.ali_host,"Alibaba@027.ctnbc-bon.net");
			// 将请求消息转换成DCC消息对应格式的XmlMessage
			XmlMessage req = new XmlMessage(true);
			String sessionId = DiameterUtils.makeSessionID(ALI_HOST) + ";"+ tb_order_id;

			req.setIp(IP);
			req.setMsgTime(receiveTime);
			req.setMID(sessionId);
			req.setUID(ALI_HOST);
			req.setSCID(whConfigService.getValue(AliParam.ability_setcharge, ""));
			req.setSIG(null);
			req.setREPTAG(0);
			req.setDATA(serviceInformation.asXML());
			req.setDataElement(element);

			SetChargeTaobao taobao = new SetChargeTaobao();
			taobao.setTb_order_id(tb_order_id);
			taobao.setAlipay_order_id(alipay_order_id);
			taobao.setDeduct_money(deduct_money);
			taobao.setOrder_status(order_status);
			taobao.setSeller_alipay_id(seller_alipay_id);
			taobao.setOut_order_id(out_order_id);
			logger.info(sessionId + ", " + taobao.toString());
			// new CallParam对象
			TaobaoHandler handler = new TaobaoHandler(body, taobao,whConfigService);
			CallParam callParam = new CallParam(req.getMID(), req.getSCID(),req, req.getUID(), handler);
			BuzProcessorManager.getInstance().processRequest(callParam);

		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 
	 * @MethodName: tbSignHandle   
	 * @Description: 淘宝预警接口  
	 * @param @param request
	 * @param @param response  
	 * @return void  
	 * @throws
	 */
	public void tbSignHandle(Request request ,Response response){
		
		String algorithm = whConfigService.getValue(AliParam.algorithm, "SHA1withRSA");
		String pubKeyValue = whConfigService.getValue(AliParam.pubKeyValue, "");
		String aliPubKeyValue = whConfigService.getValue(AliParam.aliPubKeyValue, "");
		
		long receiveTime = System.currentTimeMillis();
		PrintStream body = null;
		
		try {
			body = response.getPrintStream();
			response.set("Content-Type", "text/xml;charset=UTF-8");
			response.set("Server", "HP Asyn Server )");
			response.setDate("Date", receiveTime);
			response.setDate("Last-Modified", receiveTime);

			//  增加IP校验
			String IP = request.getClientAddress().getAddress().getHostAddress();
			
		
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream(),"utf-8")); 
	        StringBuffer stringBuffer =new StringBuffer("");
	        String temp;
	        while((temp=bufferedReader.readLine())!=null){
	            stringBuffer.append(temp);
	        }
	        bufferedReader.close();
	        String xml = stringBuffer.toString();
	        
	        String respXml = "" ;
	        respXml = DESCryptoUtil.decrypt(xml, pubKeyValue ,null) ;
	        logger.info("response from taobao:"+respXml);
	        
	        String rspUserNumber = "";
			String rspAlertValue = "";
			String rspSignType = "";
			String rspBusinessType = "" ;
			String rspSignTime = "";
			String rspSignTag = "";
//			String rspInstId = "";
			String rspMsgId = "";
	        
	        if (respXml != null) {
				Document doc = null;
				doc = DocumentHelper.parseText(respXml);
				Element root = doc.getRootElement();
				
				org.dom4j.Node node = root.selectSingleNode("//message/body/userNumber");
				if (node != null) {
					rspUserNumber = node.getStringValue();
				}
				node = root.selectSingleNode("//message/body/alertValue");
				if (node != null) {
					rspAlertValue = node.getStringValue();
				}
				node = root.selectSingleNode("//message/body/signType");
				if (node != null) {
					rspSignType = node.getStringValue();
				}
				node = root.selectSingleNode("//message/body/businessType") ;
				if(node != null){
					rspBusinessType = node.getStringValue() ;
				}
				node = root.selectSingleNode("//message/body/signTime") ;
				if(node != null){
					rspSignTime = node.getStringValue() ;
				}
				node = root.selectSingleNode("//message/signTag") ;
				if(node != null){
					rspSignTag = node.getStringValue() ;
				}
				node = root.selectSingleNode("//message/head/msgId") ;
				if(node != null){
					rspMsgId = node.getStringValue() ;
				}
	        }
	        String respBody=rspUserNumber+rspAlertValue+rspSignType+rspBusinessType+rspSignTime+"";
	        
			//验签 需要淘宝提供公钥和解密的秘钥
			if( !SignUtilsImpl.verify(respBody, rspSignTag, aliPubKeyValue, algorithm, "UTF-8")) {
				logger.info("Signature verification failed ...");
				return ;
			}
				
			// 封装淘宝的request
			Element serviceInformation = DocumentHelper.createElement("Service_Information");
			Element element = null; 
			if (rspUserNumber != null && !"".equals(rspUserNumber)) {
				element = serviceInformation.addElement("Acc_Nbr");
				element.setText(rspUserNumber);
			}
			if (rspAlertValue != null && !"".equals(rspAlertValue)) {
				element = serviceInformation.addElement("alertValue");
				element.setText(rspAlertValue);
			}
			if (rspSignType != null && !"".equals(rspSignType)) {
				element = serviceInformation.addElement("signType");
				element.setText(rspSignType);
			}
			if (rspBusinessType != null && !"".equals(rspBusinessType)) {
				element = serviceInformation.addElement("businessType");
				element.setText(rspBusinessType);
			}
			if (rspSignTime != null && !"".equals(rspSignTime)) {
				element = serviceInformation.addElement("occurTime");
				element.setText(rspSignTime);
			}
			
			String ALI_HOST = whConfigService.getValue(AliParam.aliSignHost,"Alibaba1@027.ctnbc-bon.net");
			// 将请求消息转换成DCC消息对应格式的XmlMessage
			XmlMessage req = new XmlMessage(true);
			String sessionId = DiameterUtils.makeSessionID(ALI_HOST);

			req.setIp(IP);
			req.setMsgTime(receiveTime);
			req.setMID(sessionId);
			req.setUID(ALI_HOST);
			req.setSCID(whConfigService.getValue(AliParam.aliSignSCID, "BalanceWarningSign.Taobao@027.ctnbc-bon.net"));
			req.setSIG(null);
			req.setREPTAG(0);
			req.setDATA(serviceInformation.asXML());
			req.setDataElement(serviceInformation);

			// new CallParam对象
			SignTaobaoHandler handler = new SignTaobaoHandler(body, rspMsgId, whConfigService);
			CallParam callParam = new CallParam(req.getMID(), req.getSCID(),req, req.getUID(), handler);
			BuzProcessorManager.getInstance().processRequest(callParam);

		} catch (Exception e) {
			logger.warn("Exception:"+e);
		}
	}
	
	private void errorAck(PrintStream body, String errorMsg)
			throws IOException, UnsupportedEncodingException {
		String msg = "<?xml version=\"1.0\" encoding=\"GBK\"?><isp><is_success>F</is_success>";
		msg = msg + "<error>" + errorMsg + "</error></isp>";
		body.write(msg.getBytes("GBK"));
		body.close();
	}

	/**
	 * 
	 * @MethodName: sendTbChargeRequest   
	 * @Description: 淘宝代扣请求     DCC-->HTTP
	 * @param @param callParam
	 * @param @return  
	 * @return int  
	 * @throws
	 */
	public int sendTbChargeRequest(CallParam callParam){
		
		String sign = null;
		Message request = (Message) callParam.getRequest();
		AVP avp = null;

		try {
			avp = request.find(Constants.DIAMETER_AVP_SERVICE_INFOMATION,Constants.DIAMETER_VENDOR_3GPP);
			if (avp != null) {
				AVP_Grouped serviceInfsAVP = new AVP_Grouped(avp);
				// 淘宝订单数字ID
				AVP tb_order_idAVP = serviceInfsAVP.find(92079,Constants.DIAMETER_VENDOR_CT);
				long tb_order_id = new AVP_Unsigned64(tb_order_idAVP).queryValue();
				// 商户订单号
				AVP out_order_idAVP = serviceInfsAVP.find(92080,Constants.DIAMETER_VENDOR_CT);
				String out_order_id = AVP_UTF8String.queryValue(out_order_idAVP);
				// 代扣标题
				AVP subjectAVP = serviceInfsAVP.find(92092,Constants.DIAMETER_VENDOR_CT);
				String subject = AVP_UTF8String.queryValue(subjectAVP);
				// 代扣金额
				AVP deduct_moneyAVP = serviceInfsAVP.find(92082,Constants.DIAMETER_VENDOR_CT);
				long deduct_money = new AVP_Unsigned64(deduct_moneyAVP).queryValue();
				// 付款备注
				AVP memoAVP = serviceInfsAVP.find(92083,Constants.DIAMETER_VENDOR_CT);
				String memo = AVP_UTF8String.queryValue(memoAVP);
				// 支付宝账号
				AVP seller_alipay_idAVP = serviceInfsAVP.find(92081,Constants.DIAMETER_VENDOR_CT);
				String seller_alipay_id = AVP_UTF8String.queryValue(seller_alipay_idAVP);

				String partner = whConfigService.getValue(AliParam.partner, "");
				String service = whConfigService.getValue(AliParam.service, "");
				String sign_type = whConfigService.getValue(AliParam.sign_type,
						"");
				String aliPrivatekey = whConfigService.getValue(AliParam.privateKey, "");

				StringBuilder builder = new StringBuilder();
				builder.append("deduct_money").append(deduct_money)
						.append("memo").append(memo).append("out_order_id")
						.append(out_order_id).append("partner").append(partner)
						.append("seller_alipay_id").append(seller_alipay_id)
						.append("service").append(service).append("sign_type")
						.append(sign_type).append("subject").append(subject)
						.append("tb_order_id").append(tb_order_id)
						.append(aliPrivatekey);

				try {
					sign = RSAUtil.getReadableMD5Data(builder.toString().getBytes("GBK")).toLowerCase();
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}

				String sendMSG = null;

				// service=xx&sign=xx&sign_type=xx&partner=xx&tb_order_id=xx&out_order_id=xx&deduct_money=xx&subject=xxxxx&memo=xx

				builder.delete(0, builder.length());
				try {
					builder.append("service=")
							.append(service)
							.append("&sign=")
							.append(sign)
							.append("&sign_type=")
							.append(sign_type)
							.append("&partner=")
							.append(partner)
							.append("&seller_alipay_id=")
							.append(seller_alipay_id)
							.append("&tb_order_id=")
							.append(URLEncoder.encode(tb_order_id + "", "GBK"))
							.append("&out_order_id=")
							.append(URLEncoder.encode(out_order_id + "", "GBK"))
							.append("&subject=")
							.append(URLEncoder.encode(subject + "", "GBK"))
							.append("&deduct_money=")
							.append(URLEncoder.encode(deduct_money + "", "GBK"))
							.append("&memo=")
							.append(URLEncoder.encode(memo + "", "GBK"));
				} catch (UnsupportedEncodingException e3) {
					e3.printStackTrace();
					logger.warn("URLEncoder error: " + e3.toString());
				}

				sendMSG = builder.toString();
				// 淘宝的URL
				String URL = callParam.getToNode().getServerUrl();
				logger.info(callParam.getSessionId() + ", send msg to taobao: "+ URL + "?" + sendMSG);
				HttpMethod method = new GetMethod(URL + "?" + sendMSG);
				String response = null;
				try {
					// 记录转发request信息.
					XmlMessage sendRequest = new XmlMessage(true);
					sendRequest.setMsgTime(System.currentTimeMillis());
					sendRequest.setMID(callParam.getSessionId());
					sendRequest.setSCID(callParam.getServiceContextId());
					sendRequest.setLength(sendMSG.length());
					sendRequest.setDATA(sendMSG);
					callParam.setSendRequest(sendRequest);

					int statusCode = httpClient.executeMethod(method);

					if (statusCode != HttpStatus.SC_OK) {
						logger.warn(callParam.getSessionId()+ ", sendRequest:Method failed: "+ method.getStatusLine());
						callParam.setRetCode(ResultCode.NE_CANNOT_USE);
						callParam.setResultMsg("Call taobao service err：Method failed. "+ method.getStatusLine());
						// callParam.getAsynHandler().onCallResult(callParam);
						// return -1;
					}

					response = method.getResponseBodyAsString();
					logger.info(callParam.getSessionId()+ ", get respones from taobao:" + response);

				} catch (Exception e) {
					e.printStackTrace();
					callParam.setRetCode(ResultCode.NE_CANNOT_USE);
					callParam.setResultMsg("Call taobao service err："
							+ e.getLocalizedMessage());
				} finally {
					if (method != null) {
						method.releaseConnection();
					}
				}

				if (response != null) {
					Document doc = null;
					String rsp_is_success = null;
					String rsp_error = null;
					String rsp_order_status = null;
					String rsp_tb_order_id = null;
					String rsp_out_order_id = null;
					String rsp_order_create_time = null;
					String rsp_sign = null;
					String rsp_sign_type = null;
					try {
						doc = DocumentHelper.parseText(response);
						Element root = doc.getRootElement();

						org.dom4j.Node node = root
								.selectSingleNode("//ali/is_success");
						if (node != null) {
							// 成功标志
							rsp_is_success = node.getStringValue();
						}
						node = root.selectSingleNode("//ali/sign");
						if (node != null) {
							rsp_sign = node.getStringValue();
						}
						node = root.selectSingleNode("//ali/sign_type");
						if (node != null) {
							rsp_sign_type = node.getStringValue();
						}
						if (rsp_is_success.equalsIgnoreCase("T")) {
							node = root.selectSingleNode("//ali/response/order_status");
							if (node != null) {
								rsp_order_status = node.getStringValue();
							}
							node = root.selectSingleNode("//ali/response/tb_order_id");
							if (node != null) {
								rsp_tb_order_id = node.getStringValue();
							}
							node = root.selectSingleNode("//ali/response/out_order_id");
							if (node != null) {
								rsp_out_order_id = node.getStringValue();
							}
							node = root.selectSingleNode("//ali/response/order_create_time");
							if (node != null) {
								rsp_order_create_time = node.getStringValue();
							}
							builder.delete(0, builder.length());
							builder.append("is_success").append(rsp_is_success)
									.append("order_create_time")
									.append(rsp_order_create_time)
									.append("order_status")
									.append(rsp_order_status)
									.append("out_order_id")
									.append(rsp_out_order_id)
									.append("sign_type").append(rsp_sign_type)
									.append("tb_order_id")
									.append(rsp_tb_order_id)
									.append(aliPrivatekey);
						} else {
							node = root.selectSingleNode("//ali/error");
							if (node != null) {
								rsp_error = node.getStringValue();
							}

							builder.delete(0, builder.length());
							builder.append("is_success").append(rsp_is_success)
									.append("error").append(rsp_error)
									.append("sign_type").append(rsp_sign_type)
									.append(aliPrivatekey);
						}
					} catch (DocumentException e1) {
						e1.printStackTrace();
					}

					// 签名验证
					// try {
					// sign = RSAUtil.getReadableMD5Data(
					// builder.toString().getBytes("GBK")).toLowerCase();
					// if (!sign.endsWith(rsp_sign)){
					// logger.info("sign is invalid");
					// logger.info("get sign is :"+rsp_sign);
					// logger.info("correct sign is :"+sign);
					// return -1;
					// }
					//
					// } catch (UnsupportedEncodingException e) {
					// e.printStackTrace();
					// }

					if (logger.isDebugEnabled()) {
						logger.debug(callParam.getSessionId()
								+ ": rsp_is_success=" + rsp_is_success
								+ " , rsp_order_status= " + rsp_order_status
								+ " , rsp_tb_order_id= " + rsp_tb_order_id
								+ " , rsp_out_order_id= " + rsp_out_order_id
								+ " , rsp_order_create_time= "
								+ rsp_order_create_time
								// +", rsp_error- "+rsp_error
								+ ", rsp_sign- " + rsp_sign
								+ ", rsp_sign_type- " + rsp_sign_type);
					}
					// 封装淘宝的response
					Element serviceInformation = DocumentHelper.createElement("Service_Information");
					Element element = null;
					if (rsp_order_status != null) {
						element = serviceInformation.addElement("order_status");
						element.setText(rsp_order_status);
					}
					// element = serviceInformation.addElement("tb_order_id");
					// element.setText(rsp_tb_order_id);
					// element = serviceInformation.addElement("out_order_id");
					// element.setText(rsp_out_order_id);
					if (rsp_order_create_time != null) {
						element = serviceInformation.addElement("order_create_time");
						element.setText(rsp_order_create_time);
					}
					if (rsp_is_success != null) {
						element = serviceInformation.addElement("is_success");
						element.setText(rsp_is_success);
					}

					// 请求处理异常(is_success为 F) 会返回错误码，提示出错原因。
					// if (rsp_is_success.equalsIgnoreCase("F")) {
					element = serviceInformation.addElement("error");
					if (rsp_error == null) {
						element.setText("0");
					} else {
						element.setText(rsp_error);
					}
					// }

					logger.info(callParam.getSessionId()+ ", TaoBao response to XML:"+ serviceInformation.asXML());

					XmlMessage ack = new XmlMessage(false);
					ack.setMsgTime(System.currentTimeMillis());
					ack.setMID(callParam.getSessionId());
					ack.setSIG(null);
					ack.setRC("0");
					ack.setDS("");
					ack.setRTT("");
					ack.setREPTAG(0);
					ack.setLength(serviceInformation.asXML().length());
					ack.setDATA(serviceInformation.asXML());
					ack.setDataElement(serviceInformation);

					callParam.setRecvResponse(ack);
				}
			}
		} catch (InvalidAVPLengthException e) {
			e.printStackTrace();
			logger.warn(callParam.getSessionId()+ ",convert DCC to XML error: InvalidAVPLengthException");
			callParam.setRetCode(ResultCode.VALUE_ERROR);
			callParam.setResultMsg("convert DCC to XML error:"+ e.getLocalizedMessage());
		}

		CallParam _callParam = InprogressMessageQueue.getInstance().removeProgress(callParam.getMessageUniqueID());
		if (logger.isDebugEnabled()) {
			logger.debug("remove progress form queue:"+ callParam.getMessageUniqueID());
		}
		if (_callParam == null) {
			logger.warn("msg queue not find callParam for "+ callParam.getMessageUniqueID());
		}

		callParam.getAsynHandler().onCallResult(callParam);
		return 0;
	}
	
	/**
	 * 
	 * @MethodName: sendTbWarringRequest   
	 * @Description: 淘宝预警请求   DCC-->HTTP
	 * @param @param callParam
	 * @param @return  
	 * @return int  
	 * @throws
	 */
	public int sendTbWarringRequest(CallParam callParam){
		if (logger.isDebugEnabled()) {
			logger.debug(callParam.getSessionId() + ", prepare forward request to TaoBao:" + callParam.getToNode().getServerUrl());
		}
		
		String algorithm = whConfigService.getValue(AliParam.algorithm, "SHA1withRSA");
		String priKeyValue = whConfigService.getValue(AliParam.priKeyValue, "");
		String pubKeyValue = whConfigService.getValue(AliParam.pubKeyValue, "");
		String aliPubKeyValue = whConfigService.getValue(AliParam.aliPubKeyValue, "");
		
		Message request = (Message) callParam.getRequest();
		AVP avp = null;
		String signTag = null;
		String sendMSG = null ;
		String signMSG = null ;
		String encryptMSG = null ;
		String responseMSG = null ;
		
		StringBuilder builder = new StringBuilder();
		StringBuilder signData = new StringBuilder() ;
		
		try {
			avp = request.find(Constants.DIAMETER_AVP_SERVICE_INFOMATION,Constants.DIAMETER_VENDOR_3GPP);
			if (avp != null) {
				AVP_Grouped serviceInfsAVP = new AVP_Grouped(avp);
				// 机构缩写(支付宝分配)
				AVP instIdAVP = serviceInfsAVP.find(92106,Constants.DIAMETER_VENDOR_CT);
				String instId = new AVP_UTF8String(instIdAVP).queryValue();
				// 手机号
				AVP accNbrAVP = serviceInfsAVP.find(80125,Constants.DIAMETER_VENDOR_CT);
				String accNbr = AVP_UTF8String.queryValue(accNbrAVP);
				// 运营商内部唯一标识
				AVP operatorUserIdAVP = serviceInfsAVP.find(90010,Constants.DIAMETER_VENDOR_CT);
				String operatorUserId = AVP_UTF8String.queryValue(operatorUserIdAVP);
				// 预警值
				AVP alertValueAVP = serviceInfsAVP.find(92107,Constants.DIAMETER_VENDOR_CT);
				String alertValue = new AVP_UTF8String(alertValueAVP).queryValue();
				// 当前数值：分为单位
				AVP currentValueAVP = serviceInfsAVP.find(92108,Constants.DIAMETER_VENDOR_CT);
				String currentValue = AVP_UTF8String.queryValue(currentValueAVP);
				// 业务类型
				AVP businessTypeAVP = serviceInfsAVP.find(92109,Constants.DIAMETER_VENDOR_CT);
				String businessType = AVP_UTF8String.queryValue(businessTypeAVP);
				//出发预警时间
				AVP occurTimeAVP = serviceInfsAVP.find(92110,Constants.DIAMETER_VENDOR_CT);
				String occurTime = AVP_UTF8String.queryValue(occurTimeAVP);
				//运营商唯一流水
				AVP alertNoAVP = serviceInfsAVP.find(92101,Constants.DIAMETER_VENDOR_CT);
				String alertNo = AVP_UTF8String.queryValue(alertNoAVP);

				builder.delete(0, builder.length());
				
				SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd hh:mm:ss") ;
				Date date = new Date(System.currentTimeMillis());
				
				//部分字段要联系taobao确认
				builder.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>")
						.append("<message>")
						.append("<head>")
						.append("<version>").append("1.0.1").append("</version>")
						.append("<instId>").append(instId).append("</instId>")
						.append("<type>AlertNotifyReq</type>")
						.append("<msgId>").append(callParam.getSessionId()).append("</msgId>")
						.append("<msgTime>").append(sdf.format(date)).append("</msgTime>")
						.append("<secId>").append("0002").append("</secId>")
						.append("</head>")
						.append("<body>")
						.append("<instId>").append(instId).append("</instId>")
						.append("<userNumber>").append(accNbr).append("</userNumber>")
						.append("<operatorUserId>").append(operatorUserId).append("</operatorUserId>")
						.append("<alertValue>").append(alertValue).append("</alertValue>")
						.append("<currentValue>").append(currentValue).append("</currentValue>")
						.append("<businessType>").append(businessType).append("</businessType>")
						.append("<occurTime>").append(occurTime).append("</occurTime>")
						.append("<alertNo>").append(alertNo).append("</alertNo>")
						.append("</body>") ;
						
				signData.append(instId).append(accNbr).append(operatorUserId).append(alertValue)
				        .append(currentValue).append(businessType).append(occurTime).append(alertNo);
				
				signMSG = signData.toString() ;
				signTag = SignUtilsImpl.sign(signMSG, priKeyValue, algorithm, "UTF-8");
				
				builder.append("<signTag>").append(signTag).append("</signTag>")
					   .append("</message>") ;
						
				
				sendMSG = builder.toString();
				logger.info("SendMsg to taobao ： "+sendMSG);
				//发送前对整个报文-bulider进行加密（DES加密）
				encryptMSG = DESCryptoUtil.encrypt(sendMSG,pubKeyValue,null) ;
				
				PostMethod method = new PostMethod(callParam.getToNode().getServerUrl());
				
				String response = null;
				try {
					// 记录转发request信息.
					XmlMessage sendRequest = new XmlMessage(true);
					sendRequest.setMsgTime(System.currentTimeMillis());
					sendRequest.setMID(callParam.getSessionId());
					sendRequest.setSCID(callParam.getServiceContextId());
					sendRequest.setLength(sendMSG.length());
					sendRequest.setDATA(sendMSG);
					callParam.setSendRequest(sendRequest);
					
					RequestEntity requestEntity = new StringRequestEntity(encryptMSG, "text/xml", "UTF-8");
					method.setRequestEntity(requestEntity);
					
					int statusCode = httpClient.executeMethod(method);

					if (statusCode != HttpStatus.SC_OK) {
						logger.warn(callParam.getSessionId() + ", statusCode:"+statusCode+" sendRequest:Method failed: " + method.getStatusLine());
						callParam.setRetCode(ResultCode.NE_CANNOT_USE);
						callParam.setResultMsg("Call taobao service err：Method failed. " + method.getStatusLine());
					}
					
					BufferedReader reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
					StringBuffer stringBuffer = new StringBuffer();
					String str = "";
					while((str = reader.readLine())!=null){
						stringBuffer.append(str);
					}
					response = stringBuffer.toString();
					
					logger.info("Receive Encryption Message From taobao : "+response);
					
					//对报文 解密
					responseMSG = DESCryptoUtil.decrypt(response, pubKeyValue, null) ;
					logger.info(callParam.getSessionId()+ ", get decrypted respones from taobao:" + responseMSG);

				} catch (Exception e) {
					e.printStackTrace();
					callParam.setRetCode(ResultCode.NE_CANNOT_USE);
					callParam.setResultMsg("Call taobao service err："
							+ e.getLocalizedMessage());
				} finally {
					if (method != null) {
						method.releaseConnection();
					}
				}

				if (responseMSG != null) {
					Document doc = null;
					String rspStatus = null;
					String rspFailedCode = null;
					String rspFailedReason = null;
					String respSignTag = null ;
					try {
						doc = DocumentHelper.parseText(responseMSG);
						Element root = doc.getRootElement();

						org.dom4j.Node node = root.selectSingleNode("//message/body/status");
						if (node != null) {
							// 成功标志
							rspStatus = node.getStringValue();
						}
						node = root.selectSingleNode("//message/body/failedCode");
						if (node != null) {
							rspFailedCode = node.getStringValue();
						}
						node = root.selectSingleNode("//message/body/failedReason");
						if (node != null) {
							rspFailedReason = node.getStringValue();
						}
						node = root.selectSingleNode("//message/signTag") ;
						if(node != null){
							respSignTag = node.getStringValue() ;
						}
						
					} catch (DocumentException e1) {
						logger.warn("Document Exception : "+e1);
					}
					
					String respBody=rspStatus+rspFailedCode+rspFailedReason+"";
					
					//验签 （验签时是否要用toabao提供的签名公钥）
					if( !SignUtilsImpl.verify(respBody, respSignTag, aliPubKeyValue, algorithm, "UTF-8")) {
						logger.warn("Signature verification failed...");
						return -1 ;
					}
					
					// 封装淘宝的response
					Element serviceInformation = DocumentHelper.createElement("Service_Information");
					Element element = null;
					if (rspStatus != null) {
						if(rspStatus.equalsIgnoreCase("SUCCESS")){
							element = serviceInformation.addElement("Status");
							element.setText(rspStatus);
						}else{
							element = serviceInformation.addElement("Status");
							element.setText(rspStatus);
							if(rspFailedCode != null){
								element = serviceInformation.addElement("failedCode");
								element.setText(rspFailedCode);
							}
							if(rspFailedReason != null){
								element = serviceInformation.addElement("failedReason");
								element.setText(rspFailedReason);
							}
						}
					}else{
						logger.info("response error ...");
					}

					logger.info(callParam.getSessionId() + ", TaoBaoBalWarring response to XML:" + serviceInformation.asXML());

					XmlMessage ack = new XmlMessage(false);
					ack.setMsgTime(System.currentTimeMillis());
					ack.setMID(callParam.getSessionId());
					ack.setSIG(null);
					ack.setRC("0");
					ack.setDS("");
					ack.setRTT("");
					ack.setREPTAG(0);
					ack.setLength(serviceInformation.asXML().length());
					ack.setDATA(serviceInformation.asXML());
					ack.setDataElement(serviceInformation);

					callParam.setRecvResponse(ack);
				}
			}
		} catch (InvalidAVPLengthException e) {
			e.printStackTrace();
			logger.warn(callParam.getSessionId() + ",convert DCC to XML error: InvalidAVPLengthException");
			callParam.setRetCode(ResultCode.VALUE_ERROR);
			callParam.setResultMsg("convert DCC to XML error:" + e.getLocalizedMessage());
		}

		CallParam _callParam = InprogressMessageQueue.getInstance().removeProgress(callParam.getMessageUniqueID());
		if (logger.isDebugEnabled()) {
			logger.debug("remove progress form queue:" + callParam.getMessageUniqueID());
		}
		if (_callParam == null) {
			logger.warn("msg queue not find callParam for " + callParam.getMessageUniqueID());
		}

		callParam.getAsynHandler().onCallResult(callParam);
		return 0;
	}
	
	
	
	
	public void sendRemainQueryRequest(Request request, Response response) {

		long receiveTime = System.currentTimeMillis();
		PrintStream body = null;
		
		String algorithm = whConfigService.getValue(AliParam.algorithm, "SHA1withRSA");
		String pubKeyValue = whConfigService.getValue(AliParam.remainPubKeyValue, "");
		String aliPubKeyValue = whConfigService.getValue(AliParam.remainAliPubKeyValue, "");
		try {

			body = response.getPrintStream();
			response.set("Content-Type", "text/xml;charset=UTF-8");
			response.set("Server", "HP Asyn Server )");
			response.setDate("Date", receiveTime);
			response.setDate("Last-Modified", receiveTime);

			// 增加IP校验
			String IP = request.getClientAddress().getAddress().getHostAddress();
			
		
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream(),"utf-8")); 
	        StringBuffer stringBuffer =new StringBuffer("");
	        String temp;
	        while((temp=bufferedReader.readLine())!=null){
	            stringBuffer.append(temp);
	        }
	        bufferedReader.close();
	        String xml = stringBuffer.toString();
	        
	        logger.info("response from taobao xml:"+xml);
//	        String respXml = DESCryptoUtil.decrypt(xml, pubKeyValue ,null) ;
	        String respXml = xml ;
	        logger.info("response from taobao:"+respXml);
	        
			String QueryType = "";
			String userNumber = "";
			String rspSignTag = "";
			String rspMsgId = "";
			String instId = "";
	        if (respXml != null) {
				Document doc = null;
				doc = DocumentHelper.parseText(respXml);
				Element root = doc.getRootElement();
				
				org.dom4j.Node node = root.selectSingleNode("//message/body/userNumber");
				if (node != null) {
					userNumber = node.getStringValue();
					logger.info("userNumber:"+userNumber);
				}
				node = root.selectSingleNode("//message/body/queryType");
				if (node != null) {
					QueryType = node.getStringValue();
					logger.info("QueryType:"+QueryType);
				}
				node = root.selectSingleNode("//message/signTag") ;
				if(node != null){
					rspSignTag = node.getStringValue() ;
					logger.info("signTag:"+rspSignTag);
				}
				node = root.selectSingleNode("//message/head/msgId") ;
				if(node != null){
					rspMsgId = node.getStringValue() ;
					logger.info("msgId:"+rspMsgId);
				}
				node = root.selectSingleNode("//message/head/instId") ;
				if(node != null){
					instId = node.getStringValue() ;
					logger.info("instId:"+instId);
				}
	        }
	        
	        String respBody=userNumber+QueryType+"";
	        
	        logger.info("Sign respBody:"+respBody);
	        
			//验签 需要淘宝提供公钥和解密的秘钥
			if( !SignUtilsImpl.verify(respBody, rspSignTag, aliPubKeyValue, algorithm, "UTF-8")) {
				logger.info("Signature verification failed ...");
				StringBuilder sb = new StringBuilder();
				SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss") ;
				StringBuilder resp = new StringBuilder();
				sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>")
				.append("<message>")
				.append("<head>")
				.append("<version>").append("1.0.1").append("</version>")
				.append("<instId>").append(instId).append("</instId>")
				.append("<type>RemainQueryRes</type>")
				.append("<msgId>").append(rspMsgId).append("</msgId>")
				.append("<msgTime>").append(sdf.format(new Date())).append("</msgTime>")
				.append("<secId>").append("0002").append("</secId>")
				.append("</head>")
				.append("<body>")
				.append("<userNumber>").append(userNumber).append("</userNumber>")
				.append("<value>").append("").append("</value>")
				.append("<bill>").append("").append("</bill>")
				.append("<status>").append("FAILED").append("</status>")
				.append("<failedCode>").append("0102").append("</failedCode>")
				.append("<failedReason>").append("签名验证失败").append("</failedReason>")
				.append("</body>");
		
				//如果字段中有空格，要trim掉
				resp.append(userNumber).append("").append("").append("FAILED").append("0102").append("签名验证失败");
				
				logger.info("resp :"+resp.toString());
				
				String priKeyValue = whConfigService.getValue(AliParam.remainPriKeyValue, "");
				
				String signTag = SignUtilsImpl.sign(resp.toString(), priKeyValue, algorithm ,"UTF-8");
		
				logger.info("signTag :"+signTag);
				
				sb.append("<signTag>").append(signTag).append("</signTag>").append("</message>") ;
	    		
				logger.info("response to taobao :"+sb.toString());
		
				byte[] res = sb.toString().getBytes("UTF-8");
				body.write(res);
				body.close();
				return ;
			}
				
			// 封装淘宝的request
			Element serviceInformation = DocumentHelper.createElement("Service_Information");
			
			Element balanceInformation = serviceInformation.addElement("Balance_Information");
			Element element;
			if (userNumber != null && !"".equals(userNumber)) {
				element = balanceInformation.addElement("Destination_Id");
				element.setText(userNumber);
			}
			element = balanceInformation.addElement("Destination_Id_Type");
			element.setText("2");
			element = balanceInformation.addElement("DestinationAttr");
			element.setText("2");
			element = balanceInformation.addElement("Area_Code");
			element.setText("027");
			element = balanceInformation.addElement("Query_Flag");
			element.setText("0");
			element = balanceInformation.addElement("Query_Item_Type");
			element.setText("1");
			element = balanceInformation.addElement("QueryType");
			element.setText("1");
			
			logger.info("serviceInformation:"+serviceInformation.asXML());
			
			String ALI_HOST = whConfigService.getValue(AliParam.aliRemainHost,"Alibaba1@027.ctnbc-bon.net");
			// 将请求消息转换成DCC消息对应格式的XmlMessage
			XmlMessage req = new XmlMessage(true);
			String sessionId = DiameterUtils.makeSessionID(ALI_HOST);

			req.setIp(IP);
			req.setMsgTime(receiveTime);
			req.setMID(sessionId);
			req.setUID(ALI_HOST);
			req.setSCID(whConfigService.getValue(AliParam.aliRemainCID, "QueryBalance.balanceYXHB9@027.ctnbc-bon.net"));
			req.setSIG(null);
			req.setREPTAG(0);
			req.setDATA(serviceInformation.asXML());
			req.setDataElement(serviceInformation);

			// new CallParam对象
			BalanceTaobaoHandler handler = new BalanceTaobaoHandler(body, rspMsgId,userNumber,instId, whConfigService);
			CallParam callParam = new CallParam(req.getMID(), req.getSCID(),req, req.getUID(), handler);
			BuzProcessorManager.getInstance().processRequest(callParam);
		
		}catch(Exception e){
			logger.info("Exception:"+e);
		}
	}
	

	public void sendMessageRemaindRequest(Request request, Response response) {

		long receiveTime = System.currentTimeMillis();
		PrintStream body = null;
		
		String algorithm = whConfigService.getValue(AliParam.algorithm, "SHA1withRSA");
		String priKeyValue = whConfigService.getValue(AliParam.messageRemaindPriKey, "");
		String aliPubKeyValue = whConfigService.getValue(AliParam.messageRemaindPubKey, "");
		String appId = whConfigService.getValue(AliParam.messageRemaindAppId, "2013101400001759");
		
		String errMsg = "<Service_Information><failedCode>11009</failedCode><failedReason>parameter failed</failedReason><UserId>null</UserId></Service_Information>";

		try {
			body = response.getPrintStream();
			response.set("Content-Type", "text/xml;charset=UTF-8");
			response.set("Server", "HP Asyn Server )");
			response.setDate("Date", receiveTime);
			response.setDate("Last-Modified", receiveTime);

			BufferedReader bufferedReader = new BufferedReader(
					new InputStreamReader(request.getInputStream(), "utf-8"));
			StringBuffer stringBuffer = new StringBuffer("");
			String temp;
			while ((temp = bufferedReader.readLine()) != null) {
				stringBuffer.append(temp);
			}
			bufferedReader.close();
			String xml = stringBuffer.toString();
			
			logger.info("##########################receive xml : " + xml);

			/**
			 * <Service_Information>
					<MobileNo>13387506667</MobileNo>
					<Title>[套餐余量提醒]尊敬的用户</Title>
					<TelNum>13387506667</TelNum>
					<EndTime>2014年12月29日 14点25分</EndTime>
					<Content>您套餐包含的200分钟通话时长已使用180分钟</Content>
					<Tail>超出后将按标准资费计费，请知悉。</Tail>
					<templateId>b2449364391049deafd1831bb9eae01f</templateId>
			</Service_Information>]]>
			 */
			
			String mobileNo = "";
			String title = "";
			String telNum = "";
			String endTime = "";
			String content = "";
			String tail = "";
			String templateId = "";
			
			if (xml != null) {
				Document doc = null;
				doc = DocumentHelper.parseText(xml);
				Element root = doc.getRootElement();

				org.dom4j.Node node = root
						.selectSingleNode("//Service_Information/MobileNo");
				if (node != null) {
					mobileNo = node.getStringValue();
				}
				node = root.selectSingleNode("//Service_Information/Title");
				if (node != null) {
					title = node.getStringValue();
				}
				node = root.selectSingleNode("//Service_Information/TelNum");
				if (node != null) {
					telNum = node.getStringValue();
				}
				node = root.selectSingleNode("//Service_Information/EndTime");
				if (node != null) {
					endTime = node.getStringValue();
				}
				node = root.selectSingleNode("//Service_Information/Content");
				if (node != null) {
					content = node.getStringValue();
				}
				node = root.selectSingleNode("//Service_Information/Tail");
				if (node != null) {
					tail = node.getStringValue();
				}
				node = root.selectSingleNode("//Service_Information/templateId");
				if (node != null) {
					templateId = node.getStringValue();
				}
			}
			
			if("".equals(mobileNo) || "".equals(title) || "".equals(telNum) || "".equals(endTime) || "".equals(content) || "".equals(tail) || "".equals(templateId)){
				byte[] resp = errMsg.getBytes("UTF-8");
				body.write(resp);
				body.close();
				return;
			}

			String messageRemainServerUrl = whConfigService.getValue(AliParam.messageRemaindserverURL, "");
			String responseTb = "";
			
			String bizContent = "{\"matcher\":{\"mobileNo\":\""+mobileNo+"\"},\"template\":{\"context\":{\"headColor\":\"#85be53\",\"Title\":{\"color\":\"#000000\",\"value\":\""+title+"\"},\"TelNum\":{\"color\":\"#85be53\",\"value\":\""+telNum+"\"},\"EndTime\":{\"color\":\"#85be53\",\"value\":\""+endTime+"\"},\"content\":{\"color\":\"#85be53\",\"value\":\""+content+"\"},\"Tail\":{\"color\":\"#85be53\",\"value\":\""+tail+"\"}},\"templateId\":\""+templateId+"\"}}";
			logger.info("###########################ServerUrl: " + messageRemainServerUrl);
			logger.info("###########################Send Biz Message（bizContent）: " + bizContent);
			responseTb = sendToAlipayTemplate(messageRemainServerUrl, bizContent, appId, priKeyValue);
			logger.info("########################### get respones from taobao : " + responseTb);
			
			if (responseTb != null && !"".equals(responseTb)) {
				String code = null;
				String msg = null;
				String toUserId = null;
				String respSignTag = null ;
				StringBuilder respBody = new StringBuilder();
				respBody.delete(0, respBody.length());
				
				Gson gson = new Gson();  
				MessageRemaind messageRemaind =  (MessageRemaind)gson.fromJson(responseTb, MessageRemaind.class);
				
				if(messageRemaind != null){
					respSignTag = messageRemaind.getSign();
				
					if(messageRemaind.getResponseData().getCode() != null){
						code = messageRemaind.getResponseData().getCode();
						//respBody.append("code=" + code + "&");
					}
					
					if(messageRemaind.getResponseData().getMsg() != null){
						msg = messageRemaind.getResponseData().getMsg();
						if(messageRemaind.getResponseData().getTo_user_id() != null){
							toUserId = messageRemaind.getResponseData().getTo_user_id();
							//respBody.append("msg=" + msg + "&");
							//respBody.append("to_user_id=" + toUserId);
						}else{
							//respBody.append("msg=" + msg);
						}
					}
				}
				
				logger.info("###########################"+respBody.toString());
				
				//验签 :经确认，不需验签（最好是验证签名）
				if(!SignUtilsImpl.verify(respBody.toString(), respSignTag, aliPubKeyValue, algorithm, "")) {
					logger.warn("################################Signature verification failed...");
					//return -1 ;
				}
				
				String respXML = "<Service_Information><failedCode>"+code+"</failedCode><failedReason>"+msg+"</failedReason><UserId>"+toUserId+"</UserId></Service_Information>";
				logger.info("#################response message : " + respXML);
				
				//返回信息给外部网元
				byte[] resp = respXML.getBytes("UTF-8");
				body.write(resp);
				body.close();
				
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	/**
	 * 匹配用户发送消息
	 * @MethodName: sendToAlipayTemplate   
	 * @param @param sendURL 支付宝网关地址
	 * @param @param bizContent 参数
	 * @param @param appId 电信服务窗APPID 
	 * @param @param priKeyValue 电信服务窗密钥 
	 * @param @return  
	 * @return String  
	 * @throws
	 */
	public static String sendToAlipayTemplate(String sendURL ,String bizContent ,String appId ,String priKeyValue) {
		logger.debug("---------- 调用支付宝匹配消息模板下发接口 Start ----------");
		AlipayClient client = new DefaultAlipayClient(sendURL ,appId ,priKeyValue);
		AlipayMobilePublicMessageMatcherSendRequest matcherSendRequest = new AlipayMobilePublicMessageMatcherSendRequest();
		matcherSendRequest.setBizContent(bizContent);
		AlipayMobilePublicMessageMatcherSendResponse matcherSendResponse = null;

		try {
			matcherSendResponse = client.execute(matcherSendRequest, null);
			logger.debug("---------- 调用支付宝匹配下发消息模板接口成功 end ----------");
			return matcherSendResponse.getBody();
		} catch (AlipayApiException e) {
			logger.error("调用支付宝接口出错", e);
			logger.debug("---------- 调用支付宝匹配下发消息模板接口失败 end ----------");
			return null;
		}
	}
	
}
